/////////////////////////////////////////////     File     //////////////////////////////////////////////////
// Author: James Chen
// Filename: LaserRangefinder.cpp
// Created: Sunday, August 15, 2010 9:14:40 AM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "./LaserRangefinder.h"

#define LASERWIDTH 0.25f
#define LASERHEIGHT 0.25f

////////////////////// Singleton Implementation Begins //////////////////////
CLaserRangefinder *CLaserRangefinder::m_pInstance = 0;

CLaserRangefinder::CLaserRangefinder(void) : mNumVertices(0), mNumFaces(0), md3dDevice(0), mVB(0), mIB(0)
{
	this->m_fXRot = 0.0f;
	this->m_fYRot = 0.0f;
}

CLaserRangefinder::~CLaserRangefinder(void)
{
	ReleaseCOM(mVB);
	ReleaseCOM(mIB);
}

CLaserRangefinder *CLaserRangefinder::GetInstance(void)
{
	if(!m_pInstance)
	{
		m_pInstance = new CLaserRangefinder;
	}

	return m_pInstance;
}

void CLaserRangefinder::DeleteInstance(void)
{
	if(m_pInstance)
	{
		delete m_pInstance;
		m_pInstance = 0;
	}
}
/////////////////////// Singleton Implementation Ends ///////////////////////

void CLaserRangefinder::CalculateLaser()
{

#if 0 //not working will come back to later

	D3DXVECTOR3 Left(1.0f, 0.0f, 0.0f);
	D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);

	double XDot;
	double YDot;

	D3DXVECTOR3 XProjection;
	D3DXVECTOR3 YProjection;

	//Project the vector to the Y plane first to find X rotation
	XProjection = this->m_vecTargetPosition - this->m_vecCurrentPosition;
	XProjection.x = 0;
	D3DXVec3Normalize(&XProjection, &XProjection);

	YProjection = this->m_vecTargetPosition - this->m_vecCurrentPosition;
	YProjection.y = 0;
	D3DXVec3Normalize(&YProjection, &YProjection);

	XDot = D3DXVec3Dot(&XProjection, &Up);
	YDot = D3DXVec3Dot(&YProjection, &Left);

	this->m_fXRot = acos(XDot)*DegToRad;
	this->m_fYRot = acos(YDot)*DegToRad;

#endif

	this->m_vecMidpoint = (this->m_vecTargetPosition + this->m_vecCurrentPosition) / 2;
}

void CLaserRangefinder::init(ID3D10Device* device, D3DXCOLOR color)
{
	ReleaseCOM(mVB);
	ReleaseCOM(mIB);

	md3dDevice = device;
 
	mNumVertices = 8;
	mNumFaces    = 12; // 2 per quad

	// Create vertex buffer
    Vertex vertices[] =
    {
		{D3DXVECTOR3(-LASERWIDTH+this->m_vecMidpoint.x, -LASERHEIGHT+this->m_vecMidpoint.y, -this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(-LASERWIDTH+this->m_vecMidpoint.x, +LASERHEIGHT+this->m_vecMidpoint.y, -this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(+LASERWIDTH+this->m_vecMidpoint.x, +LASERHEIGHT+this->m_vecMidpoint.y, -this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(+LASERWIDTH+this->m_vecMidpoint.x, -LASERHEIGHT+this->m_vecMidpoint.y, -this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(-LASERWIDTH+this->m_vecMidpoint.x, -LASERHEIGHT+this->m_vecMidpoint.y, +this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(-LASERWIDTH+this->m_vecMidpoint.x, +LASERHEIGHT+this->m_vecMidpoint.y, +this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(+LASERWIDTH+this->m_vecMidpoint.x, +LASERHEIGHT+this->m_vecMidpoint.y, +this->m_dMidDistance+this->m_vecMidpoint.z), color},
		{D3DXVECTOR3(+LASERWIDTH+this->m_vecMidpoint.x, -LASERHEIGHT+this->m_vecMidpoint.y, +this->m_dMidDistance+this->m_vecMidpoint.z), color},
    };

	D3DXMatrixIdentity(&m_matRotation);

	D3DXMatrixRotationYawPitchRoll(&this->m_matRotation, this->m_fYRot, this->m_fXRot, 0.0f);

	D3DXVECTOR4 temp;

#if 1
	// Scale the CTargetBox.
	for(DWORD i = 0; i < mNumVertices; ++i)
	{
		D3DXVec3Transform(&temp, &vertices[i].pos, &this->m_matRotation);
		//vertices[i].pos *= m_matRotation;

		vertices[i].pos.x = temp.x;
		vertices[i].pos.y = temp.y;
		vertices[i].pos.z = temp.z;
	}


#endif

    D3D10_BUFFER_DESC vbd;
    vbd.Usage = D3D10_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(Vertex) * mNumVertices;
    vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
    D3D10_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mVB));


	// Create the index buffer

	DWORD indices[] = {
		// front face
		0, 1, 2,
		0, 2, 3,

		// back face
		4, 6, 5,
		4, 7, 6,

		// left face
		4, 5, 1,
		4, 1, 0,

		// right face
		3, 2, 6,
		3, 6, 7,

		// top face
		1, 5, 6,
		1, 6, 2,

		// bottom face
		4, 0, 3, 
		4, 3, 7
	};

	D3D10_BUFFER_DESC ibd;
    ibd.Usage = D3D10_USAGE_IMMUTABLE;
    ibd.ByteWidth = sizeof(DWORD) * mNumFaces*3;
    ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
    D3D10_SUBRESOURCE_DATA iinitData;
    iinitData.pSysMem = indices;
    HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIB));
}

void CLaserRangefinder::draw()
{
	UINT stride = sizeof(Vertex);
    UINT offset = 0;
    md3dDevice->IASetVertexBuffers(0, 1, &mVB, &stride, &offset);
	md3dDevice->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0);
	md3dDevice->DrawIndexed(mNumFaces*3, 0, 0);
}